// -*- Mode: C++ -*-
#ifndef PATTERNEDITOR_H
#define PATTERNEDITOR_H

#include <boost/signals2.hpp>
#include <string>
#include <cstddef>

class Song;
class Track;
class SongItem;
class Pattern;
class Event;

class PatternEditor {
public:
     enum Field {
	  NoField,
	  Note,
	  CCNum0,
	  CCNum1,
	  Instrument0,
	  Instrument1,
	  Val0,
	  Val1,
	  Effect,
	  EffectArg0,
	  EffectArg1
     };
     enum ItemField {
	  Number0,
	  Number1
     };
     static const int NoRow = -1;
     static const int NoTrack = -1;
     static const int NoSongItem = -1;
     static const int Velocity = 0x40;
     typedef boost::signals2::signal<void (int)> OnInstChange;

     PatternEditor(Song *pSong=NULL);
     ~PatternEditor();
     Song* song();
     void setSong(Song *pSong);
     int curTrackNum();
     void setCurTrackNum(int num);
     Track* curTrack();
     int curSongItemNum();
     void setCurSongItemNum(int num);
     SongItem* curSongItem();
     int curPatternNum();
     void setCurPatternNum(int num);
     Pattern* curPattern();
     int curRowNum();
     void setCurRowNum(int num);     
     Field curField();
     void setCurField(Field field);
     int curItemField();
     void incItemField();
     void decItemField();
     void setCurItemField(int field);
     void incField();
     void decField();
     void setFirstField();
     Event* curEvent();
     void toggleCurEventType();
     int octave();
     void setOctave(int octave);
     int curInstNum();
     void setCurInstNum(int num);
     void setCurInstName(const std::string &name);
     void reset();
     // connect to onInstChange signal
     boost::signals2::connection onInstChange(const OnInstChange::slot_type &callback);

private:
     Song *m_pSong;
     Track *m_pTrack;
     SongItem *m_pSongItem;
     Pattern *m_pPattern;
     Event *m_pEvent;
     int m_curTrackNum;
     int m_curSongItemNum;
     int m_curRowNum;
     Field m_curField;
     int m_octave;
     int m_instNum;
     int m_itemField;
     // signal to emit when current instrument changes
     OnInstChange m_onInstChange;
};

#endif
